/**
 * 系统名称: 企业财资
 * 模块名称: repair-boot
 * 类 名 称: WxLoginFilter.java
 * 软件版权: 恒生电子股份有限公司
 * 修改记录:
 * 修改人员:
 * 修改说明:
 * ============ ============================================
 * zhanghong 创建
 * ============ ============================================
 */
package com.mt.common.core.security;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mt.common.core.config.Config;
import com.mt.common.core.utils.StringUtils;
import com.mt.common.core.utils.WxUtil;
import com.mt.common.core.web.JsonResult;
import com.mt.common.system.entity.LoginRecord;
import com.mt.common.system.service.LoginRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 *
 *
 * @author zhanghong
 * @date 2023-03-13 23:50
 */
public class WxLoginFilter extends AbstractAuthenticationProcessingFilter {
    @Autowired
    private LoginRecordService loginRecordService;
    @Resource
    private RedisTemplate<String, Long> redisTemplate;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    WxUtil wxUtil;

    ThreadLocal<String> localThread=new ThreadLocal<>();
    public WxLoginFilter(AuthenticationManager authenticationManager) {
        super("/api/wx/login");
        super.setAuthenticationManager(authenticationManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException {
        if (!request.getMethod().equals(HttpMethod.GET.name())) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }

        String openid = obtainOpenid(request);
        localThread.set(openid);
        if (openid == null || openid.length() == 0) {
            throw new BadCredentialsException("uid or openid is null.");
        }

        WeChatAuthenticationToken authRequest = new WeChatAuthenticationToken(openid);

        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
        return this.getAuthenticationManager().authenticate(authRequest);

    }

    protected String obtainOpenid(HttpServletRequest request) {
        String code = request.getParameter("code");
        return wxUtil.getOpenId(code);
    }

    /**
     * 登录成功签发token返回json数据
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                            FilterChain chain, Authentication authResult)
            throws IOException, ServletException {

        UserDetails user = (UserDetails) authResult.getPrincipal();
        String access_token = JwtUtil.sign(user.getUsername(), user.getPassword());
        // 记录登录日志
        loginRecordService.saveAsync(user.getUsername(), LoginRecord.TYPE_LOGIN, null, request);
        PrintWriter out = response.getWriter();
        // 返回json数据
        response.setContentType("application/json;charset=UTF-8");

        out.write(JSON.toJSONString(JsonResult.ok("登录成功").put("access_token", access_token)
                .put("token_type", JwtUtil.TOKEN_TYPE)));
        out.flush();
    }

    /**
     * 登录失败处理
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                              AuthenticationException e) throws IOException, ServletException {
        String openId =localThread.get();
        response.setContentType("application/json;charset=UTF-8");
        PrintWriter out = response.getWriter();
        JsonResult result;
        if (e instanceof UsernameNotFoundException) {
            result = JsonResult.error("账号不存在");
            loginRecordService.saveAsync("openId"+openId, LoginRecord.TYPE_ERROR, "账号不存在", request);
        } else if (e instanceof LockedException) {
            result = JsonResult.error("账号被锁定");
            loginRecordService.saveAsync("openId"+openId, LoginRecord.TYPE_ERROR, "账号被锁定", request);
        } else if(e instanceof BadCredentialsException) {
            result = JsonResult.error("未绑定微信账号,即将跳转到注册");
            result.put("openId",openId);
        }else {
            result = JsonResult.error(e.getMessage());
        }
        out.write(JSON.toJSONString(result));
        out.flush();
    }
}
